﻿using UnityEngine;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UBlockly.UI;
using System.Reflection;

namespace UBlockly.Scriptable
{
    public sealed class ILTranslate
    {
        #region 函数库导入
        public static void LoadApi(IBlockApi obj)
        {
            Init();
            System.Type type = obj.GetType();
            var methods = type.GetMethods();
            foreach (var method in (methods))
            {
                int methodParamLength = 0;
                System.Type methodReturnType = method.ReturnType;
                System.Type delType = null;
                if (method.GetParameters() != null) methodParamLength = method.GetParameters().Length;
                if (method.GetCustomAttribute(typeof(BlockFunctionAttribute)) == null
                    || (methodReturnType != typeof(void) && methodReturnType != typeof(bool)
                    && methodReturnType != typeof(int) && methodReturnType != typeof(string)))
                {
                    if (method.GetCustomAttribute(typeof(BlockFunctionAttribute)) != null)
                        Debug.LogError($"函数{method.Name}定义错误，返回值{methodReturnType.Name},参数长度{methodParamLength}");
                    continue;
                }

                if (methodReturnType == typeof(void) && methodParamLength == 1)
                {
                    delType = typeof(System.Action<System.Action>);
                }
                else if (methodReturnType == typeof(void) && methodParamLength == 2)
                {
                    if (method.GetParameters()[0].ParameterType == typeof(bool))
                        delType = typeof(System.Action<bool, System.Action>);
                    else if (method.GetParameters()[0].ParameterType == typeof(int))
                        delType = typeof(System.Action<int, System.Action>);
                    else if (method.GetParameters()[0].ParameterType == typeof(string))
                        delType = typeof(System.Action<string, System.Action>);
                }
                else if (methodReturnType == typeof(bool) && methodParamLength == 0)
                {
                    delType = typeof(System.Func<bool>);
                }
                else if (methodReturnType == typeof(bool) && methodParamLength == 1)
                {
                    if (method.GetParameters()[0].ParameterType == typeof(bool))
                        delType = typeof(System.Func<bool, bool>);
                    else if (method.GetParameters()[0].ParameterType == typeof(int))
                        delType = typeof(System.Func<int, bool>);
                    else if (method.GetParameters()[0].ParameterType == typeof(string))
                        delType = typeof(System.Func<string, bool>);
                }
                else if (methodReturnType == typeof(int) && methodParamLength == 0)
                {
                    delType = typeof(System.Func<int>);
                }
                else if (methodReturnType == typeof(int) && methodParamLength == 1)
                {
                    if (method.GetParameters()[0].ParameterType == typeof(bool))
                        delType = typeof(System.Func<bool, int>);
                    else if (method.GetParameters()[0].ParameterType == typeof(int))
                        delType = typeof(System.Func<int, int>);
                    else if (method.GetParameters()[0].ParameterType == typeof(string))
                        delType = typeof(System.Func<string, int>);
                }
                else if (methodReturnType == typeof(string) && methodParamLength == 0)
                {
                    delType = typeof(System.Func<string>);
                }
                else if (methodReturnType == typeof(string) && methodParamLength == 1)
                {
                    if (method.GetParameters()[0].ParameterType == typeof(bool))
                        delType = typeof(System.Func<bool, string>);
                    else if (method.GetParameters()[0].ParameterType == typeof(int))
                        delType = typeof(System.Func<int, string>);
                    else if (method.GetParameters()[0].ParameterType == typeof(string))
                        delType = typeof(System.Func<string, string>);
                }

                if (delType == null)
                {
                    Debug.LogError("some param format error,please check:" + method.Name);
                    continue;
                }
                var del = System.Delegate.CreateDelegate(delType, obj, method);
                Debug.Log($"注册函数{method.Name}");
                RegistFunction(delType, method.Name, del);
            }
        }
        #endregion

        #region 函数类型获取Node类型
        public static System.Type GetNodeType(ILFuncType funcType)
        {
            System.Type target = null;
            try
            {
                target = System.Type.GetType($"UBlockly.UI.{funcType.ToString()}TypeNode");
            }
            catch (System.NullReferenceException e)
            {
                Debug.LogError($"ilfunctype {funcType.ToString()} to node type error,no suitable typenode");
            }
            return target;
        }
        #endregion

        #region 自带函数初始化
        static void Init()
        {
            RegistFunction("GetString", GetString);
            RegistFunction("GetInt", GetInt);
            RegistFunction("GetBool", GetBool);
            //RegistFunction("IfElseCondition",)
        }
        #endregion
        #region 函数注册
        static Dictionary<string, StringReturnFunction> stringReturnMap = new Dictionary<string, StringReturnFunction>();
        static Dictionary<string, IntReturnFunction> intReturnMap = new Dictionary<string, IntReturnFunction>();
        static Dictionary<string, BoolReturnFunction> boolReturnMap = new Dictionary<string, BoolReturnFunction>();
        static Dictionary<string, VoidReturnFunction> voidReturnMap = new Dictionary<string, VoidReturnFunction>();
        static void RegistFunction(System.Type functionType, string funname, System.Delegate del)
        {
            if (typeof(System.Action<System.Action>) == functionType)
            {
                RegistFunction(funname,(System.Action<System.Action>)del);
            }
            else if(typeof(System.Action<bool,System.Action>)== functionType)
            {
                RegistFunction(funname,(System.Action<bool,System.Action>)del);
            }
            else if(typeof(System.Action<int,System.Action>)== functionType)
            {
                RegistFunction(funname,(System.Action<int,System.Action>)del);
            }
            else if(typeof(System.Action<string,System.Action>)== functionType)
            {
                RegistFunction(funname,(System.Action<string,System.Action>)del);
            }
            else if(typeof(System.Func<bool>)== functionType)
            {
                RegistFunction(funname,(System.Func<bool>)del);
            }
            else if(typeof(System.Func<bool,bool>)== functionType)
            {
                RegistFunction(funname,(System.Func<bool,bool>)del);
            }
            else if(typeof(System.Func<bool,int>)== functionType)
            {
                RegistFunction(funname,(System.Func<bool,int>)del);
            }
            else if(typeof(System.Func<bool,string>)== functionType)
            {
                RegistFunction(funname,(System.Func<bool,string>)del);
            }
            else if(typeof(System.Func<int>)== functionType)
            {
                RegistFunction(funname,(System.Func<int>)del);
            }
            else if(typeof(System.Func<int,bool>)== functionType)
            {
                RegistFunction(funname,(System.Func<int,bool>)del);
            }
            else if(typeof(System.Func<int,int>)== functionType)
            {
                RegistFunction(funname,(System.Func<int,int>)del);
            }
            else if(typeof(System.Func<int,string>)== functionType)
            {
                RegistFunction(funname,(System.Func<int,string>)del);
            }
            else if(typeof(System.Func<string>)== functionType)
            {
                RegistFunction(funname,(System.Func<string>)del);
            }
            else if(typeof(System.Func<bool,string>)== functionType)
            {
                RegistFunction(funname,(System.Func<bool,string>)del);
            }
            else if(typeof(System.Func<int,string>)== functionType)
            {
                RegistFunction(funname,(System.Func<int,string>)del);
            }
            else if(typeof(System.Func<string,string>)== functionType)
            {
                RegistFunction(funname,(System.Func<string,string>)del);
            }
        }
        static void RegistFunction(string funname, System.Func<string> func)
        {
            if (!stringReturnMap.ContainsKey(funname))
            {
                stringReturnMap.Add(funname, new StringReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<bool,string> func)
        {
            if (!stringReturnMap.ContainsKey(funname))
            {
                stringReturnMap.Add(funname, new StringReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<int, string> func)
        {
            if (!stringReturnMap.ContainsKey(funname))
            {
                stringReturnMap.Add(funname, new StringReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<string, string> func)
        {
            if (!stringReturnMap.ContainsKey(funname))
            {
                stringReturnMap.Add(funname, new StringReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<int> func)
        {
            if (!intReturnMap.ContainsKey(funname))
            {
                intReturnMap.Add(funname, new IntReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<bool,int> func)
        {
            if (!intReturnMap.ContainsKey(funname))
            {
                intReturnMap.Add(funname, new IntReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<int,int> func)
        {
            if (!intReturnMap.ContainsKey(funname))
            {
                intReturnMap.Add(funname, new IntReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<string,int> func)
        {
            if (!intReturnMap.ContainsKey(funname))
            {
                intReturnMap.Add(funname, new IntReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<bool> func)
        {
            if (!boolReturnMap.ContainsKey(funname))
            {
                boolReturnMap.Add(funname, new BoolReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<bool,bool> func)
        {
            if (!boolReturnMap.ContainsKey(funname))
            {
                boolReturnMap.Add(funname, new BoolReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<int,bool> func)
        {
            if (!boolReturnMap.ContainsKey(funname))
            {
                boolReturnMap.Add(funname, new BoolReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Func<string,bool> func)
        {
            if (!boolReturnMap.ContainsKey(funname))
            {
                boolReturnMap.Add(funname, new BoolReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Action<System.Action> func)
        {
            if (!voidReturnMap.ContainsKey(funname))
            {
                voidReturnMap.Add(funname, new VoidReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Action<bool,System.Action> func)
        {
            if (!voidReturnMap.ContainsKey(funname))
            {
                voidReturnMap.Add(funname, new VoidReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Action<int,System.Action> func)
        {
            if (!voidReturnMap.ContainsKey(funname))
            {
                voidReturnMap.Add(funname, new VoidReturnFunction(func));
            }
            else
            {
                Debug.LogError("函数重复注册，检查");
            }
        }
        static void RegistFunction(string funname, System.Action<string,System.Action> func)
        {
            if (!voidReturnMap.ContainsKey(funname))
            {
                voidReturnMap.Add(funname, new VoidReturnFunction(func));
            }
            else
            {
                Debug.LogError($"函数{funname}重复注册，检查");
            }
        }
        #endregion

        #region    inner function
        static bool GetBool(bool value)
        {
            return value;
        }
        static int GetInt(int value)
        {
            return value;
        }
        static string GetString(string value)
        {
            return value;
        }
        #endregion
        #region return void
        public static void ExF(string funcName, System.Action endCallback, object defaultParam = null)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, ""));
            if (defaultParam == null)
            {
                VoidReturnFunction ilFun = null;
                if (voidReturnMap.TryGetValue(funcName, out ilFun))
                {
                    ilFun.EndCallback = endCallback;
                    ilFun.Excute();
                }
            }
            else if (defaultParam is int)
            {
                ExF(funcName, (int)defaultParam, endCallback);
            }
            else if (defaultParam is bool)
            {
                ExF(funcName, (bool)defaultParam, endCallback);
            }
            else if (defaultParam is string)
            {
                ExF(funcName, (string)defaultParam, endCallback);
            }
        }

        public static void ExF(string funcName, bool param,System.Action endCallback)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            VoidReturnFunction ilFun = null;
            if (voidReturnMap.TryGetValue(funcName, out ilFun))
            {
                ilFun.EndCallback = endCallback;
                ilFun.Excute(param);
            }
        }

        public static void ExF(string funcName, int param, System.Action endCallback)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            VoidReturnFunction ilFun = null;
            if (voidReturnMap.TryGetValue(funcName, out ilFun))
            {
                ilFun.EndCallback = endCallback;
                ilFun.Excute(param);
            }
        }

        public static void ExF(string funcName, string param, System.Action endCallback)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            VoidReturnFunction ilFun = null;
            if (voidReturnMap.TryGetValue(funcName, out ilFun))
            {
                ilFun.EndCallback = endCallback;
                ilFun.Excute(param);
            }
            else
            {
                Debug.LogError($"function:{funcName} not regist");
            }
        }
        #endregion
        #region return bool
        public static bool BExF(string funcName, object defaultParam)
        {
            if (defaultParam != null)
            {
                return BExF(funcName, (bool)defaultParam);
            }
            return BExF(funcName);
        }

        public static bool BExF(string funcName)
        {
            Debug.Log(string.Format("执行函数：{0}", funcName));
            BoolReturnFunction ilFun = null;
            if (boolReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute();
            }
            Debug.LogError("NoDefine function");
            return false;
        }

        public static bool BExF(string funcName, bool param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            BoolReturnFunction ilFun = null;
            if (boolReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute(param);
            }
            Debug.LogError("NoDefine function");
            return false;
        }

        public static bool BExF(string funcName, int param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            BoolReturnFunction ilFun = null;
            if (boolReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute(param);
            }
            Debug.LogError("NoDefine function");
            return false;
        }

        public static bool BExF(string funcName, string param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            BoolReturnFunction ilFun = null;
            if (boolReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute(param);
            }
            Debug.LogError("NoDefine function");
            return false;
        }
        #endregion
        #region return Int
        public static int IExF(string funcName,object defaultParam)
        {
            if (defaultParam != null)
            {
                return IExF(funcName, (int)defaultParam);
            }
            return IExF(funcName);
        }

        public static int IExF(string funcName)
        {
            Debug.Log(string.Format("执行函数：{0}", funcName));
            IntReturnFunction ilFun = null;
            if (intReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute();
            }
            Debug.LogError("NoDefine function:" + funcName);
            return 0;
        }
        public static int IExF(string funcName, bool param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            IntReturnFunction ilFun = null;
            if (intReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute(param);
            }
            Debug.LogError("NoDefine function:" + funcName);
            return 0;
        }
        public static int IExF(string funcName, int param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            IntReturnFunction ilFun = null;
            if (intReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute(param);
            }
            Debug.LogError("NoDefine function:" + funcName);
            return 0;
        }
        public static int IExF(string funcName, string param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            IntReturnFunction ilFun = null;
            if (intReturnMap.TryGetValue(funcName, out ilFun))
            {
                return ilFun.Excute(param);
            }
            Debug.LogError("NoDefine function:"+funcName);
            return 0;
        }
        #endregion
        #region return String
        public static string SExF(string funcName, object defaultParam)
        {
            if (defaultParam != null)
            {
                return SExF(funcName, (string)defaultParam);
            }
            return SExF(funcName);
        }
        public static string SExF(string funcName)
        {
            Debug.Log(string.Format("执行函数：{0}", funcName));
            StringReturnFunction strFun = null;
            if (stringReturnMap.TryGetValue(funcName, out strFun))
            {
                return strFun.Excute();
            }
            Debug.LogError("NoDefine function:" + funcName);
            return "";
        }
        public static string SExF(string funcName, bool param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            StringReturnFunction strFun = null;
            if (stringReturnMap.TryGetValue(funcName, out strFun))
            {
                return strFun.Excute(param);
            }
            Debug.LogError("NoDefine function:" + funcName);
            return "";
        }
        public static string SExF(string funcName, int param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            StringReturnFunction strFun = null;
            if (stringReturnMap.TryGetValue(funcName, out strFun))
            {
                return strFun.Excute(param);
            }
            Debug.LogError("NoDefine function:" + funcName);
            return "";
        }
        public static string SExF(string funcName, string param)
        {
            Debug.Log(string.Format("执行函数：{0},参数：{1}", funcName, param));
            StringReturnFunction strFun = null;
            if (stringReturnMap.TryGetValue(funcName, out strFun))
            {
                return strFun.Excute(param);
            }
            Debug.LogError("NoDefine function:"+funcName);
            return "";
        }
        #endregion
    }
}
namespace UBlockly.Scriptable
{
    class StringReturnFunction
    {
        System.Func<string> func1;
        System.Func<bool, string> func2;
        System.Func<int, string> func3;
        System.Func<string, string> func4;
        public StringReturnFunction(System.Func<string> func)
        {
            func1 = func;
        }
        public StringReturnFunction(System.Func<bool, string> func)
        {
            func2 = func;
        }
        public StringReturnFunction(System.Func<int, string> func)
        {
            func3 = func;
        }
        public StringReturnFunction(System.Func<string, string> func)
        {
            func4 = func;
        }
        public string Excute()
        {
            return func1.Invoke();
        }
        public string Excute(bool param)
        {
            return func2.Invoke(param);
        }
        public string Excute(int param)
        {
            return func3.Invoke(param);
        }
        public string Excute(string param)
        {
            return func4.Invoke(param);
        }
    }

    class IntReturnFunction
    {
        System.Func<int> func1;
        System.Func<bool, int> func2;
        System.Func<int, int> func3;
        System.Func<string, int> func4;
        public IntReturnFunction(System.Func<int> func)
        {
            func1 = func;
        }
        public IntReturnFunction(System.Func<bool, int> func)
        {
            func2 = func;
        }
        public IntReturnFunction(System.Func<int, int> func)
        {
            func3 = func;
        }
        public IntReturnFunction(System.Func<string, int> func)
        {
            func4 = func;
        }
        public int Excute()
        {
            return func1.Invoke();
        }
        public int Excute(bool param)
        {
            return func2.Invoke(param);
        }
        public int Excute(int param)
        {
            return func3.Invoke(param);
        }
        public int Excute(string param)
        {
            return func4.Invoke(param);
        }
    }

    class BoolReturnFunction
    {
        System.Func<bool> func1;
        System.Func<bool, bool> func2;
        System.Func<int, bool> func3;
        System.Func<string, bool> func4;
        public BoolReturnFunction(System.Func<bool> func)
        {
            func1 = func;
        }
        public BoolReturnFunction(System.Func<bool, bool> func)
        {
            func2 = func;
        }
        public BoolReturnFunction(System.Func<int, bool> func)
        {
            func3 = func;
        }
        public BoolReturnFunction(System.Func<string, bool> func)
        {
            func4 = func;
        }
        public bool Excute()
        {
            return func1.Invoke();
        }
        public bool Excute(bool param)
        {
            return func2.Invoke(param);
        }
        public bool Excute(int param)
        {
            return func3.Invoke(param);
        }
        public bool Excute(string param)
        {
            return func4.Invoke(param);
        }
    }

    class VoidReturnFunction
    {
        System.Action<System.Action> func1;
        System.Action<bool, System.Action> func2;
        System.Action<int, System.Action> func3;
        System.Action<string, System.Action> func4;
        int functionCallCounter = 0;
        bool runningFlag = false;
        public System.Action EndCallback;
        public VoidReturnFunction(System.Action<System.Action> func)
        {
            func1 = func;
        }
        public VoidReturnFunction(System.Action<bool, System.Action> func)
        {
            func2 = func;
        }
        public VoidReturnFunction(System.Action<int, System.Action> func)
        {
            func3 = func;
        }
        public VoidReturnFunction(System.Action<string, System.Action> func)
        {
            func4 = func;
        }
        public void Excute()
        {
            runningFlag = false;
            func1.Invoke(ContinueFunc);
        }
        public void Excute(bool param)
        {
            runningFlag = false;
            func2.Invoke(param, ContinueFunc);
        }
        public void Excute(int param)
        {
            runningFlag = false;
            func3.Invoke(param, ContinueFunc);
        }
        public void Excute(string param)
        {
            runningFlag = false;
            func4.Invoke(param, ContinueFunc);
        }
        public bool GetRunningState()
        {
            return runningFlag;
        }
        void ContinueFunc()
        {
            functionCallCounter++;
            runningFlag = true;
            EndCallback?.Invoke();
        }
    }
}

